<?PHP


/**
* SAPID Kernel Module.
* Defines basic parser class.
*
* $Log: kernel.lib.php,v $
* Revision 1.19  2006/05/18 12:33:56  toxin76
* added a | PHP open tag to row 749
*
* Revision 1.18  2006/02/20 08:26:49  sheiko
* *** empty log message ***
*
* Revision 1.17  2005/11/07 15:33:55  sheiko
* Added readonly attribute of SDC
*
* Revision 1.16  2005/11/02 10:36:50  sheiko
* Fixed preg_quote params in chack_val() function
*
* Revision 1.15  2005/10/31 07:51:02  sheiko
* Analize <sapi:apply exp="somefunction()" />
*
* Revision 1.14  2005/09/01 15:58:15  sheiko
* *** empty log message ***
*
* Revision 1.13  2005/09/01 11:00:41  mephius
* fixed bug with duplicate qc values
*
* Revision 1.12  2005/08/29 05:39:10  sheiko
* FireFox Support for Insert Image/File
*
* Revision 1.11  2005/08/22 05:34:08  sheiko
* load_qc_data() was changed for new interface of images/files adding. It needs to program Firefox support
*
* Revision 1.10  2005/08/03 09:20:27  toxin76
*  embendded <sapi:for-each... > now works correct in ddc (it makes a temporary save from the vars of the outer for-each and load them back before finishing its work)
*
*
* Revision 1.9  2005/07/18 05:53:31  mephius
* fixed bug with quotes in queries with type "string"
*
* Revision 1.8  2005/07/04 11:10:28  sheiko
* New QC-image attributes - resize and addiconsize. Sample of using resize="width*height"
*
* Revision 1.7  2005/06/30 09:13:08  sheiko
* *** empty log message ***
*
* Revision 1.6  2005/06/30 08:20:14  mephius
* added ability of quering data as lists (HTML SELECT in edit mode) {temporary}
*
* Revision 1.5  2005/06/16 06:54:36  mephius
* Fixed small bug with incorrect trace mode info while in admin mode
*
* Revision 1.4  2005/06/14 13:21:52  mephius
* Formatted header of this file
*
*
* @package kernel
* @author $Author: toxin76 $ 
* @version $Id: kernel.lib.php,v 1.19 2006/05/18 12:33:56 toxin76 Exp $
* @since SAPID v.0.9
* @copyright (c) by Mephius
*/


/**
* SAPI Core class. Needs to be extended with DAL (Data Abstraction Layer).
* Parses XML Sapiens objects in the given template.
* @package kernel
* @author $Author: toxin76 $ 
* @version $Id: kernel.lib.php,v 1.19 2006/05/18 12:33:56 toxin76 Exp $
* @since SAPID v.0.9
* @copyright (c) by Mephius
*/

if (!defined("SAPID_STARTED")) die("Hacking attempt!");

class sapi_core {
	/**
	* Current value of the template
	* @var string (may be string or filepath)
	*/
	var $template="";

	/**
	* This instance name
	* @var string (may be string or filepath)
	*/
	var $name="";

	/**
	* Query containers parsing passed flag
	* @var boolean
	*/
	var $qc_passed=false;

	/**
	* Processing instructions parsing passed flag
	* @var boolean
	*/
	var $pi_passed=false;

	/**
	* Static Data Containers parsing passed flag
	* @var boolean
	*/
	var $sdc_passed=false;

	/**
	* Dynamic Data Containers parsing passed flag
	* @var boolean
	*/
	var $ddc_passed=false;

	/**
	* Value parsing passed flag
	* @var boolean
	*/
	var $val_passed=false;

	/**
	* Parser Environment
	* @var array
	*/
	var $env=array();

	/**
	* Found SAPI objects
	* @var array
	*/
	var $sapi=array();

	/**
	* Temp. array of parsed <sapi:code> instructions
	* @var array
	*/
	var $code=array();

	/**
	* Current element (used by XML Parser)
	* @var string
	*/
	var $element="";

	/**
	* Counter
	* @var integer
	*/
	var $count=0;

	/**
	* Code Array
	* @var array
	*/
	var $codearr=array();

	/**
	* Parser Stack value
	* @var array
	*/
	var $stack=array();

	/**
	* Current handler
	* @var string
	*/
	var $handler="";

	/**
	* Temporary Parser Environment
	* @var string
	*/
	var $thandler="";

	/**
	* Parser Mode
	* @var integer
	*/
	var $mode=0;

	/**
	* Parsing error
	* @var string
	*/
	var $error="";


	/**
	* Class constructor
	* @param mixed $template initial value of template to parse
	* @param array $env initial environmant array
	* @param string $handler this instance handler	
	* @param string $name this instance name
	* @return object
	*/
	function sapi_core ($template, $env=false, $handler="", $name="sapi_env"){
		
		if(!$env){
			$env=$this->env=&$GLOBALS["env"];
		}else{
			$this->env=$env;
		}
		$this->mode = (isset($env["mode"])?$env["mode"]:0);
		$this->template=$template;
		if($name=="sapi_env") {
			$this->load_template($template);
			$this->load_pagedata();
			if(is_array($this->env)) $this->env=($this->init_stack($this->env) + $this->env);
			$this->check_predefinition();
		}

		$this->handler=$handler;
		$this->name=$name;

		return $this;
	} //\\sapi_core


	/**
	 * Appends to an array it's "serialized" copy
	 * $arr["one"]["two"] will be accessable as $arr["one.two"]
	 *
	 * @param array $arr array to serialize
	 * @return array
	 */
	function init_stack($arr){
		$arr2=array();
		if(empty($arr)) return $arr;
		$flag_end=0;
		while (!empty($arr)){
			foreach ($arr as $key=>$value) {
				if (is_array($value)) {
					unset($arr[$key]);
					foreach ($value as $k=>$v) {
						if(is_array($v)) $arr[$key . "." . $k]=$v; else $arr2[$key . "." . $k]=$v;
					}
				}else{
					unset($arr[$key]);
				}
			}
		}
		return $arr2;
	} //\\init_stack


	/**
	 * XML Parser start element handler
	 *
	 * @param object $parser XML Parser Resourse ID
	 * @param string $name element name
	 * @param array $attribs element attributes
	 */
	function sapi_start($parser, $name, $attribs)
	{
		$this->element=$name;
		if ($name=="SAPI:WHEN" and $attribs["EXP"]){

			//$data=preg_replace("/([a-zA-Z_\d\.]+)\.value/is", "\$this->env[\"\\1\"]", $attribs["EXP"]);


			$this->code.="if (".preg_replace("/([a-zA-Z_\d\.]+)\.value/is", "\$this->env[\"\\1\"]", $attribs["EXP"]).") {\n";
		}elseif ($name=="SAPI:FOR-EACH"){
			if(!isset($attribs["NAME"])) $attribs["NAME"]="enum";
			$this->code.="
			\$filename=ROOT_PATH . \"usr/extensions/".preg_replace("/(.*)\(.*\)$/isU", "\\1", $attribs["SELECT"]).".inc.php\";
			if(is_file(\$filename)) include_once(\$filename);
			\$temp_create=true;\$temp_save_array=array();\$temp_tenv=array();
					
			\$" . $attribs["NAME"] . "=" . $attribs["SELECT"] . ";
			".(TRACE?"
			\$result['count'][]=count(\$" . $attribs["NAME"] . ");
			\$result['slice'][]=array_slice(\$" . $attribs["NAME"] . ", 0, 1);
			\$result['handler'][]=\$this->handler.'.'.".$attribs["NAME"].";
			\$result['array'][]='\$" . $attribs["NAME"] . "=" . addslashes($attribs["SELECT"]) . "';
			":"")."
			if(is_array(\$".$attribs["NAME"]."))
			foreach (\$".$attribs["NAME"]." as \$key=>\$value){
			unset(\$arr);
			
						
			if(!strpos(\"".$attribs["NAME"]."\", \$this->handler)) {
				\$th=\$this->handler;
				\$this->handler.=\".".$attribs["NAME"]."\";
				\$this->thandler.=\".this\";
			}
             if(is_array(\$tenv)){
                foreach (\$tenv as \$k=>\$entry) if (is_array(\$entry)) {
                    foreach (\$entry as \$k2=>\$tv)	{
                        if(\$temp_create){
                            
                           if (isset(\$this->env[\$k.\".\".\$k2]))  \$temp_save_array[\$k.\".\".\$k2]=\$this->env[\$k.\".\".\$k2];
                            \$temp_tenv[\$k][\$k2]=\$tv;
                        }
                        unset(\$this->env[\$k.\".\".\$k2]);

                    }
                    unset(\$this->env[\$this->handler]);
                }
                \$temp_create=false;
            }
					
			\$tenv=array();
			\$tenv[\$this->handler]=\$value;
			\$tenv[\$this->thandler]=\$value;
			\$arr[\$th][\"".$attribs["NAME"]."\"]=\$value;


			\$this->env=\$this->env + \$this->init_stack(\$tenv);// + \$arr;\n";

		}elseif ($name=="SAPI:CODE"){
			$this->code.="
		\$iter_stack= '" . addcslashes(stripcslashes(trim($this->codearr[$this->count])), "'") . "';
		if(strstr(\$iter_stack, '.value')){
			\$tmp_sapi_obj =& new sapi_parser(stripslashes(\$iter_stack), \$this->env, \$this->handler, \"tmp_sapi_env\");
			\$this->stack.=\$tmp_sapi_obj->build_page();
		}else \$this->stack.=\$iter_stack;";

			$this->count++;
		}

	} //\\sapi_start

	/**
	 * XML Parser end element handler
	 *
	 * @param object $parser XML Parser Resourse ID
	 * @param string $name element name
	 */
	function sapi_end($parser, $name)
	{
		if ($name=="SAPI:FOR-EACH") $this->code .= "\$this->handler=preg_replace(\"/(.*)(\.[a-zA-z\d]+)$/\", \"\\\\1\", \$this->handler);
		\$this->thandler=preg_replace(\"/\.this$/\", \"\", \$this->thandler);
		\n}\n
		if (is_array(\$temp_save_array)){
            foreach (\$temp_save_array as \$key=>\$value)\$this->env[\$key]=\$value;
            foreach (\$temp_tenv as \$key1=>\$value1)foreach (\$value1 as \$key2=>\$value2) \$tenv[\$key1][\$key2]=\$value2;
        }
		
	  ";
		if ($name=="SAPI:WHEN") {
			$this->code.="\n}\n";
		}
	} //\\sapi_end

	/**
	 * XML Parser character data handler
	 *
	 * @param object $parser XML Parser Resourse ID
	 * @param string $name element name
	 */
	function sapi_data($parser, $data)
	{
		if ($this->element=="SAPI:EXP" and trim($data)!="") {
			$this->code.= "if (".preg_replace("/([a-zA-Z_\d\.]+)\.value/is", "\$this->env[\"\\1\"]", $data).") {";
		}
	} //\\sapi_data


	/**
	 * Initializes sapi containers from file
	 *
	 * @param string $filename
	 */
	function sapi_init($name, $type){

		$sapi=$this->load_sapi($name, $type);

		//		preg_match_all("/<sapi:qc (.*)>(.*)<\/sapi:qc>/isU", $sapi, $tqc, PREG_PATTERN_ORDER);
		preg_match_all("/<sapi:sdc (.*)>(.*)<\/sapi:sdc>/isU", $sapi, $tsdc, PREG_PATTERN_ORDER);
		preg_match_all("/<sapi:ddc (.*)>(.*)<\/sapi:ddc>/isU", $sapi, $tddc, PREG_PATTERN_ORDER);
		unset($sapi);
		$sapi_containers=array_merge(/*$tqc,*/ $tsdc, $tddc);
		//unset($tqc);
		unset($sdc);
		unset($ddc);

		if (is_array($sapi_containers))
		foreach ($sapi_containers as $k=>$value){
			foreach ($value as $key=>$container) {
				$p = xml_parser_create();
				xml_parser_set_option($p, XML_OPTION_CASE_FOLDING, 0);
				xml_parser_set_option($p, XML_OPTION_SKIP_WHITE, 1);
				xml_parse_into_struct($p, $container, $values, $tags);
				xml_parser_free($p);
				foreach ($tags as $tag=>$index) {
					//					if ($tag=="sapi:qc") {
					//						$data=$values[$index[0]]["attributes"];
					//						$data["value"]=$sapi_containers[$k+2][$key];
					//						$this->sapi["qc"][$data["name"]]=$data;
					//					}
					if ($tag=="sapi:sdc") {
						$data=$values[$index[0]]["attributes"];
						$data["value"]=$sapi_containers[$k+2][$key];
						$this->sapi["sdc"][$data["name"]]=$data;
					}
					if ($tag=="sapi:ddc") {
						$data=$values[$index[0]]["attributes"];
						$cache_fname=ROOT_PATH . "usr/system/cache/ddc." . $data["name"] . ".cache";
						if(is_file($cache_fname) and OBJ_CACHE and !TRACE and @filemtime($cache_fname)>@filemtime($filename)){
							$fp=@fopen($cache_fname, "r");
							if (!$fp) message_die("Filed opening <b>" . $cache_fname . "</b> for reading!");
							else{
								$size=filesize($cache_fname);
								$data["exec"]=fread($fp, $size);
								$this->sapi["ddc"][$data["name"]]=$data;
								fclose($fp);
							}
						}else{
							preg_match("/<sapi:name>(.*)<\/sapi:name>/isU", $sapi_containers[$k+2][$key], $name);
							preg_match("/<sapi:email>(.*)<\/sapi:email>/isU", $sapi_containers[$k+2][$key], $email);
							preg_match("/<sapi:url>(.*)<\/sapi:url>/isU", $sapi_containers[$k+2][$key], $url);
							preg_match("/<sapi:comments>(.*)<\/sapi:comments>/isU", $sapi_containers[$k+2][$key], $comment);
							$sapi_containers[$k+2][$key]=preg_replace("/<sapi:author>(.*)<\/sapi:author>/isU", "", $sapi_containers[$k+2][$key]);
							$sapi_containers[$k+2][$key]=preg_replace("/<sapi:comments>(.*)<\/sapi:comments>/isU", "", $sapi_containers[$k+2][$key]);
							$data["author"]["name"]=$name[1];
							$data["author"]["email"]=$email[1];
							$data["author"]["url"]=$url[1];
							$data["comments"]=$comment[1];


							$ddc_body=$sapi_containers[$k+2][$key];
							preg_match_all("/<sapi:code.*>(.*)<\/sapi:code>/isU", $ddc_body, $tcode, PREG_PATTERN_ORDER);
							$this->codearr=$tcode[1];
							$ddc_body=preg_replace("/<sapi:code(.*)>/isU", "<sapi:code\\1><![CDATA[", $ddc_body);
							$ddc_body=str_replace("</sapi:code>", "]]></sapi:code>", $ddc_body);
							$sp=xml_parser_create();
							xml_set_element_handler($sp, array(&$this, 'sapi_start'), array(&$this, 'sapi_end'));
							xml_set_character_data_handler($sp, array(&$this, 'sapi_data'));
							xml_parser_set_option($sp, XML_OPTION_SKIP_WHITE, 1);
							$this->count=0;
							$this->code="";
							if(!xml_parse($sp, trim($ddc_body))) {
								if(DEBUG){
									$ddc_body=str_replace("<![CDATA[", "", $ddc_body);
									$ddc_body=str_replace("]]>", "", $ddc_body);
									$arr=explode("\n", trim($ddc_body));
									$code='<span style="color: red;"><b>Error:</b>&nbsp;' . xml_error_string(xml_get_error_code($sp)) . " at line ".xml_get_current_line_number($sp)."</span><br /><br />";
									foreach ($arr as $key=>$line) {
										if($key==xml_get_current_line_number($sp)-1) $code.='<div style="background-color: #FF9797"><div style="float: left; clear: left; width: 20px; background-color: #dfdfdf;">'.($key+1).".</div>".str_replace("\t", "&nbsp;&nbsp;&nbsp;&nbsp;", htmlentities($line))."</div>"; else $code.='<div style="float: left; clear: left; width: 20px; background-color: #dfdfdf;">'.($key+1).".</div>".str_replace("\t", "&nbsp;&nbsp;&nbsp;&nbsp;", htmlentities($line))."<br />";
									}
									$this->env["sapi_error_cnt"]++;
									$data["exec"]="\$error=<<<EOC\n<div style=\"border: 1px solid red; color: white; background-color: red; font-weight: bold; cursor: pointer;\" align=\"center\" onclick=\"if(document.getElementById('sapi_error_".$this->env["sapi_error_cnt"]."').style.display!='block') document.getElementById('sapi_error_".$this->env["sapi_error_cnt"]."').style.display='block'; else document.getElementById('sapi_error_".$this->env["sapi_error_cnt"]."').style.display='none';\">SAPI Error #".$this->env["sapi_error_cnt"]."</div><div id=\"sapi_error_".$this->env["sapi_error_cnt"]."\" style=\"display: none;margin-top: 2px; position: absolute; background-color: #efefef; width: 700px; border: 1px solid Gray; padding: 5px;\">" . $code."</div>\nEOC;\n \$this->stack=\$error;";
								}else $data["exec"]="";
							}else{
								$data["exec"]=trim($this->code);
							}
							xml_parser_free($sp);

							if(OBJ_CACHE and !TRACE){
								$fp=@fopen(ROOT_PATH . "usr/system/cache/ddc." . $data["name"] . ".cache", "w+");
								if (!$fp) message_die("Failed opening <b>" . ROOT_PATH . "usr/system/cache/" . $tag . "." . $data["name"] . "cache" . "</b> for writing!");
								else{
									fwrite($fp, $data["exec"]);
									fclose($fp);
								}
							}

							$this->sapi["ddc"][$data["name"]]=$data;
						}
					}
				}
			}
		}
		unset($sapi_containers);
	} //\\sapi_init


	/**
	 * Loads query container data
	 *
	 * @param string $name
	 * @param string $query_type
	 * @return string
	 */
		function load_qc_data($name, $attribs){
		// mod toxin this is a temporary fix which prevent to overwrite the page environment variables in the infochannel.lib.php
		if(isset($this->env["infoChannel." . $name])) $data=$this->env["infoChannel." . $name];
		elseif (isset($this->env["page." . $name])) $data=$this->env["page." . $name];
		// mod toxin
		if($attribs["group"] AND $this->env["user.usergroup"]!="wheel" AND $this->env["user.usergroup"]!=$attribs["group"]) {
			$data = false;
		}
		
		
		// Checking DDC with DEFAULT attribute
		if(isset($attribs["default"])) {
			if($attribs["default"] AND !$data)	$data=$attribs["default"];
		}

		if ($this->mode!=1 and !$GLOBALS["qc"][$name]) {
			switch ($attribs["type"]) {
				case "image":
				if(@is_file(ROOT_PATH . "usr/templates/" . $data)){
					$stat=@getimagesize(ROOT_PATH . "usr/templates/" . $data);
					$data='<img border="0" alt="" src="'.$this->env["http_path"].'usr/templates/'.$data.'" '.$stat[3].' />';
				}else $data="";
				break;

				case "file":
				if(@is_file(ROOT_PATH . "usr/templates/" . $data)){
					$size=@filesize(ROOT_PATH . "usr/templates/" . $data);

					if($size) {
						$size=(round($size/1024, 1)>=1?round($size/1024)." KB":$size." B");
						$info=pathinfo(ROOT_PATH . "usr/templates/" . $data);
						$data= str_replace("files/", "", $data) . " (" . (is_file(ROOT_PATH.'usr/system/images/'.strtolower($info["extension"]).'.gif')?'<img src="'.$this->env["http_path"].'usr/system/images/'.strtolower($info["extension"]).'.gif" width="16" height="16" alt="'.strtoupper($info["extension"]).' File" />&nbsp;':'') . $size . ")<br />";
					}
				}else $data="";
			}
			// Delivery mode: Checking DDC in SRC attribute
			if((!isset($attribs["accessarea"]) or $attribs["accessarea"]=="global")){
				if(isset($attribs["src"]) and strstr($attribs["src"], "ddc.")){
					$sparser = new sapi_parser("<sapi:apply name=\"".$attribs["src"]."\"><sapi:param name=\"uri\">".$data."</sapi:param></sapi:apply>", &$this->env, "", "ddc_sapi_env");
					$res=$sparser->build_page();
					unset($sparser);
					$data=trim($res);
					if($data=="") $data="";
				}
			} else $data="";
		}elseif ($this->mode==1 and !$GLOBALS["qc"][$name]) {
			if((!isset($attribs["accessarea"]) or $attribs["accessarea"]=="edit" or $attribs["accessarea"]=="global")){
				$qc_label = 'qc.'.$name.'.value';
				if( defined("TRACEMODE") )
				$block_header = ($attribs["title"]?$attribs["title"].' ('.$qc_label.")":$qc_label);
				else
				$block_header = ($attribs["title"]?$attribs["title"]:$qc_label);



				//Querying data
				switch ($attribs["type"]) {
					case "publication":
					$type="qc";
					ob_start();
					include(ROOT_PATH . "usr/system/editor.php");
					$data=ob_get_contents();
					ob_end_clean();
					break;

					case "checkbox":
					$data='
						<div style="width: '.($attribs["width"]?$attribs["width"]."px":"").';" class="sapid_qc_marker"><input type="checkbox" '.($data?'checked="checked"':'').' value="1" id="string_'.$name.'">'.$block_header.'&nbsp;</div>';
					$GLOBALS["form_fields"].='<input type="hidden" name="container[qc]['.$name.']" value="'.$name.'">
						<input type="hidden" name="'.$name.'" id="field_'.$name.'">';
					$GLOBALS["action_script"].="if(document.getElementById('string_" . $name . "').checked) document.getElementById('field_" . $name . "').value = 1; else document.getElementById('field_" . $name . "').value = 0;\n";
					break;

					/* Adding by Dmitry Sheiko */
					case "date":
					if(!defined("PHP_DATEFORMAT")) $date_data = date("d/m/Y");
					else $date_data = date(PHP_DATEFORMAT);
					$data='
						<div style="width: '.($attribs["width"]?$attribs["width"]."px":"").';" class="sapid_qc_marker">'.$block_header.'</div><input type="text" value="'.($data?$data:$date_data).'" id="string_'.$name.'" style="width: '.($attribs["width"]?$attribs["width"]:"200").'px;" onKeyPress="if(window.event.keyCode<47 || window.event.keyCode>57) return false;" />';
					$GLOBALS["form_fields"].='<input type="hidden" name="container[qc]['.$name.']" value="'.$name.'">
						<input type="hidden" name="'.$name.'" id="field_'.$name.'">';
					$GLOBALS["action_script"].="document.getElementById('field_" . $name . "').value = document.getElementById('string_" . $name . "').value;\n";
					break;

					case "string":
					$data='
					<div style="width: '.($attribs["width"]?$attribs["width"]."px":"").';" class="sapid_qc_marker">'.$block_header.'</div><input type="text" value="'.str_replace('"', "&quot;", $data).'" id="string_'.$name.'" style="width: '.($attribs["width"]?$attribs["width"]:"200").'px;" />';
					$GLOBALS["form_fields"].='<input type="hidden" name="container[qc]['.$name.']" value="'.$name.'">
						<input type="hidden" name="'.$name.'" id="field_'.$name.'">';
					$GLOBALS["action_script"].="document.getElementById('field_" . $name . "').value = document.getElementById('string_" . $name . "').value;\n";
					break;

					case "select":
					if(isset($attribs["src"]) and strstr($attribs["src"], "ddc.")){
						$sparser =& new sapi_parser("<sapi:apply name=\"".$attribs["src"]."\" />", &$this->env, "", "ddc_sapi_env");
						$res=$sparser->build_page();
						unset($sparser);
						$res=str_replace("<option value=\"".$data."\">", "<option value=\"".$data."\" selected>", $res);
						$data='
						<div style="width: '.($attribs["width"]?($attribs["width"]-5)."px":"100%").';" class="sapid_qc_marker">'.$block_header.'</div>
						<select  style="width: '.($attribs["width"]?$attribs["width"]."px":"100%").';" id="select_'.$name.'">'.$res.'</select>';
						$GLOBALS["form_fields"].='<input type="hidden" name="container[qc]['.$name.']" value="'.$name.'">
						<input type="hidden" name="'.$name.'" id="field_'.$name.'">';
						$GLOBALS["action_script"].="document.getElementById('field_" . $name . "').value = document.getElementById('select_" . $name . "').value;\n";
					}
					break;


					case "image":
					if(@is_file(ROOT_PATH . "usr/templates/" . $data)){
						$stat=@getimagesize(ROOT_PATH . "usr/templates/" . $data);
						$img='<img src="'.$this->env["http_path"].'usr/templates/'.$data.'" '.$stat[3].'  name="src_'.$name.'" id="src_'.$name.'" /><br />';
					} else $img='<img src="'.$this->env["http_path"].'usr/templates/x.gif" width="1" height="1"  name="src_'.$name.'" id="src_'.$name.'" /><br />';

					// Sheiko: AddIconSize is wrong attribute. Needs to use IconSize attribute
					$hwidth=$stat[0]-4;
					if($hwidth>300) $hwidth=300;
					$data='
						<form name="imageform_'.$name.'" id="imageform_'.$name.'" enctype="multipart/form-data" method="post">
						<div  style="width: '.($hwidth?$hwidth:120).'px;" class="sapid_qc_marker">'.$block_header.'</div>
						'.$img.'
						<input type="hidden" name="container[qc]['.$name.']" value="'.$name.'">
						<input type="hidden" id="image_'.$name.'" name="'.$name.'" value="'.$data.'">
						<input type="hidden" name="resize_'.$name.'" value="'.$attribs["resize"].'" />
						<input type="hidden" name="iconsize_'.$name.'" value="'.$attribs["iconsize"].'" />
						<input type="hidden" name="backup_'.$name.'" value="'.$data.'" />
					
						<div style="margin-top: 3px;">
							<input type="image" src="'.$GLOBALS["http_path"].'usr/system/images/but4.gif" type="button" onClick="window.open(\''.$GLOBALS["http_path"].'usr/system/insert_qcimage.php?qc='.$name.'&resize='.$attribs["resize"].'&iconsize='.$attribs["iconsize"].'&id='.$this->env["document.id"].'&data='.$data.'\', \'displayWindow\',\'width=500,height=500,status=yes,toolbar=no,menubar=no, scrollbars=auto, resizable=yes\'); return false;" name="upload_'.$name.'" alt="'.$GLOBALS["lang"]["ieeditor"]["Insert_Image"].'">
							<input type="image" src="'.$GLOBALS["http_path"].'usr/system/images/but3.gif" onClick="return DeleteImageObj(\''.$name.'\');" name="delete_'.$name.'" alt="'.$GLOBALS["lang"]["Delete"].'">
						</div>
							</form>';
					
					// Sheiko: Needs data fields of images
					$GLOBALS["form_fields"].='<input type="hidden" name="container[qc]['.$name.']" value="'.$name.'">
						<input type="hidden" name="'.$name.'" id="field_'.$name.'">';
					$GLOBALS["action_script"].="document.getElementById('field_" . $name . "').value = document.getElementById('image_" . $name . "').value;\n";					
					
					break;

					case "file":
					if(is_file(ROOT_PATH . "usr/templates/" . $data)){
						$size=@filesize(ROOT_PATH . "usr/templates/" . $data);

						if($size) {
							$size=(round($size/1024, 1)>=1?round($size/1024)." KB":$size." B");
							$info=pathinfo(ROOT_PATH . "usr/templates/" . $data);
							$img= '<a href="'.$GLOBALS["http_path"].'/usr/templates/'.$data.'" target="_blank">'.preg_replace("/^files\//is", "", $data) ."</a> (".(is_file(ROOT_PATH.'usr/system/images/'.strtolower($info["extension"]).'.gif')?'<img src="'.$this->env["http_path"].'usr/system/images/'.strtolower($info["extension"]).'.gif" width="16" height="16" alt="'.strtoupper($info["extension"]).' File" />&nbsp;':'') . $size . ")<br />";
						}
					}

					$data='
						<form name="fileform_'.$name.'" id="fileform_'.$name.'" enctype="multipart/form-data" method="post">
						<div  style="width: 115px;" class="sapid_qc_marker">'.$block_header.'</div>
						<div id="show_'.$name.'">'.$img.'</div>
						<input type="hidden" name="container[qc]['.$name.']" value="'.$name.'">
						<input type="hidden" id="file_'.$name.'" name="'.$name.'" value="'.$data.'">
						<div style="margin-top: 3px;">
							<input type="image" src="'.$GLOBALS["http_path"].'usr/system/images/but4.gif" type="button" onClick="window.open(\''.$GLOBALS["http_path"].'usr/system/insert_qcfile.php?qc='.$name.'&id='.$this->env["document.id"].'\', \'displayWindow\',\'width=350,height=100,status=yes,toolbar=no,menubar=no, scrollbars=auto, resizable=yes\'); return false;" name="upload_'.$name.'" alt="'.$GLOBALS["lang"]["ieeditor"]["Insert_File"].'">
							<input type="image" src="'.$GLOBALS["http_path"].'usr/system/images/but3.gif" onClick="return DeleteFileObj(\''.$name.'\');" name="delete_'.$name.'" alt="'.$GLOBALS["lang"]["Delete"].'">
						</div>
						</form>';
					
					// Sheiko: Needs data fields of images
					$GLOBALS["form_fields"].='<input type="hidden" name="container[qc]['.$name.']" value="'.$name.'">
						<input type="hidden" name="'.$name.'" id="field_'.$name.'">';
					$GLOBALS["action_script"].="document.getElementById('field_" . $name . "').value = document.getElementById('file_" . $name . "').value;\n";	
										
					break;

				}
			}else $data="";
		}else{
			if(isset($attribs["accessarea"]) and $attribs["accessarea"]!="global") $data="";
		}
		if(isset($data)) return trim($data); else  return "";
	} //\\load_qc_data





	/**
	 * Checks current value of template for incapsulated Query Containers
	 *
	 */
function check_qc(){
		$this->qc_passed=0;
		while ($this->qc_passed==0) {
			$this->qc_passed=1;
			preg_match_all("/<sapi:apply\s+name=\"(qc\.[a-zA-Z\.\d_\-]+)\"\s+(.*)(\/>|>\s*(.*)\s*<\/sapi:apply>){1}/isU", $this->template, $matches);
			if (count($matches[1])!=0) {
				$qc=$matches[1];
				$this->qc_passed=0;
				foreach ($qc as $c=>$name) {
					$this->handler=$env_name=preg_replace("/qc\.(.*)\.value/", "\\1", trim($name));
					$this->thandler="this";
					if($matches[2][$c]){
						preg_match_all("/([a-zA-Z\.\d\-_]+)=\"([^\"]+)\"/", $matches[2][$c], $mm);
						$attribs=array();
						if(is_array($mm[1]))
						foreach ($mm[1] as $akey=>$attrib) {
							$attribs[$attrib]=$mm[2][$akey];
						}
					}
					if($matches[4][$c]){
						preg_match_all("/<sapi:param\s+name=\"([a-zA-Z\d_\.]+)\">(.*)<\/sapi:param>/isU", $matches[4][$c], $pmatches);
						if(is_array($pmatches[1]))
						foreach ($pmatches[1] as $kp=>$param) {
							$this->env[$this->handler.".param.".$param]=$this->env[$this->thandler.".param.".$param]=$pmatches[2][$kp];
							$pname[]=$this->thandler.".param.".$param;
							$pname[]=$this->thandler.".param.".$param;
						}
					}

					$data=$this->load_qc_data($env_name, $attribs);
					$this->template=preg_replace("/<sapi:apply\s+name=\"$name\"\s+.*(\/>|>.*<\/sapi:apply>)/isU", $data, $this->template);
					$GLOBALS["qc"][$name]=1;
					$this->handler=$this->thandler="";
					if(is_array($pname))
					foreach ($pname as $param) {
						unset($this->env[$param]);
					}

				}
			}
			unset($matches);
		}

	} //\\check_qc


	/**
	 * Parse predefined values in the template
	 *
	 */
	function check_predefinition(){

		// Step 1. Looking for predeterminations script

		preg_match_all("/<link\s+rel=\"predeterminations\"\s+href=\"(.*?)\"[^>]*\/>/is", $this->template, $matches);
		if (count($matches[1])!=0) {
			foreach($matches[1] as $fetch) {
				@include(ROOT_PATH.$fetch);
			}
		}
	}

	function check_constants(){

		// Step 2. Parse predefined values in the template

		preg_match_all("/&([a-zA-Z\.\d_\-]+)\.value;/isU", $this->template, $matches);
		if (count($matches[1])!=0) {
			foreach($matches[1] as $fetch) {
				$this->template = str_replace("&".$fetch.".value;", $this->env[$fetch], $this->template);
			}
		}
	}

	/**
	 * Checks current value of template for incapsulated Processing Instructions
	 *
	 */
	function check_pi(){
		while ($this->pi_passed==0) {
			$this->pi_passed=1;
			preg_match_all("/(<\?(EXTERNAL|SYSTEM|PHP)(.*)\?>)/isU", $this->template, $matches, PREG_PATTERN_ORDER);
			if (count($matches[0])!=0) {
				$pi=$matches[1];
				unset($matches);
				$this->pi_passed=0;
				$this->qc_passed=0;
				unset($patterns);
				foreach ($pi as $eval_code) {
					$patterns[]=$eval_code;
					$code=preg_replace("/(<\?(EXTERNAL|SYSTEM|PHP))(.*)(\?>)/isU", "\\3", $eval_code);
					ob_start();
					if(@eval($code . " return true;")) $replacements[]=ob_get_contents(); else $replacements[]=$this->compile_error($code);
					//$replacements[]=ob_get_contents();
					ob_end_clean();
				}
				foreach ($patterns as $key=>$pattern) {
					$this->template=str_replace($pattern, $replacements[$key], $this->template);
				}
			}
		}
	} //\\check_pi

	/**
	 * Checks current value of template for incapsulated Static Data Containers
	 *
	 */
	function check_sdc(){
		$this->sdc_passed=0;
		while ($this->sdc_passed==0) {
			$this->sdc_passed=1;
			
			//preg_match_all("/<sapi:apply\s+name=\"(sdc\.[a-zA-Z\.\d\-_]+)\"\s+\/>/isU", $this->template, $matches);
			preg_match_all("/<sapi:apply\s+name=\"(sdc\.[a-zA-Z\.\d_\-]+)\"\s+(.*)(\/>|>)/isU", $this->template, $matches);

			if (count($matches[1])!=0) {
				$sdc=$matches[1];
				$this->sdc_passed=0;
				$this->qc_passed=0;
				$this->pi_passed=0;
				foreach ($sdc as $c=>$name) {
					$original_tag = $matches[0][$c];
					
					// Get SDC attributes
					if($matches[2][$c]) {
						preg_match_all("/([a-zA-Z\.\d\-_]+)=\"([^\"]+)\"/", $matches[2][$c], $mm);
						$attribs=array();
						if(is_array($mm[1]))
						foreach ($mm[1] as $akey=>$attrib) {
							$attribs[strtolower($attrib)]=$mm[2][$akey];
						}
					}
					
					$name=preg_replace("/sdc\.(.*)\.value/i", "\\1", trim($name));
					//Load container
					$this->sapi_init($name, "sdc");
					$data=$this->sapi["sdc"][$name]["value"];
					if ($this->mode==1 and !$GLOBALS["sdc"][$name]) {//Only if this container isn't processed yet
						$this->names[]=$name;
						$this->sapi["sdc"][$name]["passed"]=1;
						$type="sdc";
						// What is value of READONLY?
						if($attribs["readonly"] AND $attribs["readonly"]!="none") {
							$data = $this->sapi["sdc"][$name]["value"];
						} else {
							ob_start();
							include(ROOT_PATH . "usr/system/editor.php");
							$data=ob_get_contents();
							ob_end_clean();
						}
					}
					$this->template=preg_replace("/".preg_quote($original_tag, "/")."/isU", $data, $this->template);
					$GLOBALS["sdc"][$name]=1;
				}
			}
			unset($matches);
		}
	} //\\check_sdc

	/**
	 * Checks current value of template for Dynamic Data Containers
	 *
	 */
	function check_ddc(){
		$this->ddc_passed=0;
		while ($this->ddc_passed==0) {
			$this->ddc_passed=1;
			preg_match_all("/<sapi:apply\s+name=\"(ddc\.[a-zA-Z\.\d_\-]+)\"\s*(redirect=\"([a-zA-Z\d_]+)\")?\s*(\/>|>\s*(.*)\s*<\/sapi:apply>){1}/isU", $this->template, $matches);
			if (count($matches[1])!=0) {
				$ddc=$matches[1];
				$params=$matches[5];
				$redirect=$matches[3];
				unset($matches);
				$this->ddc_passed=0;
				foreach ($ddc as $c=>$name) {
					$env_name=preg_replace("/ddc\.(.*)\.value/i", "\\1", trim($name));
					//Load container

					$this->sapi_init($env_name, "ddc");
					$this->handler=$env_name;
					$this->thandler="this";
					$this->stack="";
					if($params[$c]){
						preg_match_all("/<sapi:param\s+name=\"([a-zA-Z\d_]+)\">(.*)<\/sapi:param>/isU", $params[$c], $matches);
						if(is_array($matches[1]))
						foreach ($matches[1] as $kp=>$param) $this->env[$this->handler.".param.".$param]=$this->env[$this->thandler.".param.".$param]=$matches[2][$kp];
					}

					/* Adding by Dmitry Sheiko */
					$GLOBALS["this_sapi"] = $this->sapi["ddc"][$env_name];
					$ts=getmicrotime();


					$res=@eval("\n " . $this->sapi["ddc"][$env_name]["exec"] . " return true;");
					//if(!$res) d($this->sapi["ddc"][$env_name]["exec"]);


					$etime=number_format(getmicrotime()-$ts, 3);
					unset($GLOBALS["this_sapi"]);

					unset($this->sapi["ddc"][$env_name]["exec"]);
					if(isset($tenv) and is_array($tenv)){
						foreach ($tenv as $key=>$entry)
						if (is_array($entry)) foreach ($entry as $key2=>$value)
						unset($this->env[$key.".".$key2]);
					}
					unset($this->env[$this->handler]);
					if($redirect[$c]) {
						$this->env[$redirect[$c]]=$this->stack;
						$this->stack="";
					}
					if(TRACE) {
						$res="";
						if (is_array($result)) {
							$counter=0;

							//d($result);

							while (count($result["count"])>0) {
								$counter++;

								$cnt=array_shift($result["count"]);
								$func=array_shift($result["array"]);
								$slice=array_shift($result["slice"]);

								$handler=array_shift($result["handler"]);
								if(is_array($slice[0]) and count($slice[0]>0)){
									$sl='<div style="position: absolute; margin-left: 5px;"><a onclick="sa_toggle(\'sa_ddc_'.$env_name.'_'.$counter.'\', \'l\')"><img id="sa_ddc_'.$env_name.'_'.$counter.'_status" src="'.$this->env["http_path"].'usr/system/images/lplus.gif" /></a></div><div id="sa_ddc_'.$env_name.'_'.$counter.'" style="border: 1px dashed Gray; display: none; margin: 2px; padding: 2px;">';
									foreach ($slice[0] as $key=>$value) {
										$sl.='<i style="color: Gray;">@'.gettype($value) . '</i> <b style="color: Gray">' . $handler . "." . $key . '</b><br />';
									}
									$sl.='</div><br />';
								}
								$res.='<span style="color: #660000; font-weight: bold;">Enum:</span> <i style="color: green;">'.$func.'</i><br />Results: ' . $cnt . "" . $sl . "";
								$sl="<br />";
							}

						}
						$ddc_info='<div style="position: absolute;"><a href="#" onclick="window.open(\'/usr/system/plotter.php?name='.$env_name.'.xml\', \'alg\', \'scrollbars=yes,status=no,resizable=1,toolbar=no,width=400,height=400\')"><img src="/usr/system/images/uml.gif" alt="Show DDC Algorythm" width="12" hight="14" border="0" /></a></div>&nbsp;&nbsp;&nbsp;&nbsp;<b>ddc.'.$env_name.'.value</b> : '.$etime.' sec : <span style="color: green" >' . $this->sapi["ddc"][$env_name]["comments"] . '</span><br /><br />
						' . $res;
						$this->stack='<div onclick="sa_toggle(\'sa_ddc_'.$env_name.'\')" style="cursor: pointer; font-size: 10px; font-weight: bold; font-family: Verdana, Arial; color: white; background-color: #4A9EDD; padding: 2px;">ddc.'.$env_name.'.value&nbsp;<div style="position: absolute;"><img id="sa_ddc_'.$env_name.'_status" src="'.$this->env["http_path"].'usr/system/images/ilplus.gif" /></div></div><div style="display: none; padding: 2px; margin-top: 2px; position: absolute; border: 1px dashed Gray; background-color: #efefef; font-size: 11px; font-family: Verdana, Arial; z-index: 2000; width: 600px;" id="sa_ddc_'.$env_name.'">'.$ddc_info.'</div><div style="border: 1px dashed Gray; padding: 2px; margin: 0px; ">' . $this->stack . '</div>';
					}
					unset($result);
					$this->template=preg_replace("/<sapi:apply\s+name=\"$name\"\s*(redirect=\".*\")?\s*(\/>|>.*<\/sapi:apply>)/isU", $this->stack, $this->template, 1);
				}
			}
		}
	} //\\check_ddc

	/**
	 * Checks current value of template for Environment Variables
	 *
	 */
	function check_val(){
		$this->val_passed=0;
		
			// sapi:apply EXP analysis
			if( preg_match("/sapi:apply\s+exp/is", $this->template) ) {
				preg_match_all("/<sapi:apply\s+exp=\"(.*?)\"\s+\/>/is", $this->template, $matches);
				if (count($matches[1])!=0) { // Get all expressions (commands)
				
					foreach($matches[1] as $orCommand) {
						if($orCommand) {
							$Command = $orCommand; // Parse all variables in the command
							preg_match_all("/([a-zA-Z_\d\.\-]+)\.value/is", $Command, $Variables);
							if($Variables[1]) {
								foreach($Variables[1] as $Var) { // Modify variables to ENV values
									$Command = str_replace($Var.".value", "'".$this->env[$Var]."'", $Command);
								}
							}
						@eval("\$result = ".$Command."; return false;"); // Execute command functions
						$this->template=preg_replace("/<sapi:apply\s+exp=\"".preg_quote($orCommand, "/")."\"\s+\/>/isU", $result, $this->template);
						}
					}
				}
			}
			
		
		while ($this->val_passed==0) {
			$this->val_passed=1;
			preg_match_all("/<sapi:apply\s+name=\"([a-zA-Z_\d\.\-]+)\.value\"\s+\/>/is", $this->template, $matches);
			foreach ($matches[1] as $key=>$value) if (strpos($value, "ddc.")!==false or strpos($value, "sdc.")!==false or strpos($value, "qc.")!==false) unset($matches[1][$key]);
			if (count($matches[1])!=0) {
				$val=$matches[1];
				unset($matches);
				$this->qc_passed=0;
				$this->pi_passed=0;
				$this->sdc_passed=0;
				$this->ddc_passed=0;
				$this->val_passed=0;
				foreach ($val as $c=>$name) {
					if(!isset($this->env[$name])) $this->env[$name]="";
					$this->template=preg_replace("/<sapi:apply\s+name=\"$name\.value\"\s+\/>/isU", $this->env[$name], $this->template);
				}
			}

			$res=preg_match_all("/sapi:([a-zA-Z]+)=\"([a-zA-Z_\d\.\-\(\),'\/\s]+)\"/isU", $this->template, $matches);
			if(is_array($matches[2]) and $res!=0){
				foreach ($matches[2] as $k=>$aexp) {
					if (preg_match("/lt\s?\(|leq\s?\(|gt\s?\(|geq\s?\(|eq\s?\(|neq\s?\(|add\s?\(|substract\s?\(multiply\s?\(|divide\s?\(/isU", $aexp)) {

						preg_match_all("/([a-zA-Z\d\.\-_]+)\.value/is", $aexp, $m);
						if(is_array($m[1])){
							foreach ($m[1] as $key=>$value) {
								$patterns[$key]=$m[0][$key];
								$replacements[$key]=$this->env[$m[1][$key]];
							}
							$aexp=str_replace($patterns, $replacements, $aexp);
						}
						@eval("\$rr=" . $aexp . ";");
						$this->template=str_replace($matches[0][$k], $matches[1][$k] . '="'.$rr.'"', $this->template);
						unset($matches[0][$k]);
						unset($matches[1][$k]);
						unset($matches[2][$k]);
					}
				}




				$patterns=array();
				$replacements=array();
				if (is_array($matches[1]))
				foreach ($matches[1] as $key=>$value) {
					$patterns[$key]=$matches[0][$key];
					if(preg_match("/qc/i", $matches[2][$key])) $replacements[$key]=$value . '="'.$this->env["page.".strtoupper(str_replace(array("qc.", ".value"), "", $matches[2][$key]))].'"';
					else
					$replacements[$key]=$value . '="'.$this->env[str_replace(".value", "", $matches[2][$key])].'"';
				}
				$this->template=str_replace($patterns, $replacements, $this->template);
			}
		}
	} //\\check_val

	/**
	 * Implement all includes
	 * 
	 * @return string
	 */
	function check_inludes() {
		preg_match_all("/<sapi:include href=\"(.*)\"(.*)>/isU", $this->template, $matches);
		if (count($matches[1])!=0) {
			foreach($matches[1] as $key=>$value) {
				if(!file_exists(ROOT_PATH."usr/templates/".$value)) $insert = "";
				else {
					if(preg_match("/parse=\"php\"/isU", $matches[2][$key])) {
						ob_start();
						include(ROOT_PATH."usr/templates/".$value);
						$insert = ob_get_contents();
						ob_end_clean();
					} else $insert = file_get_contents(ROOT_PATH."usr/templates/".$value);
				}
				$this->template = str_replace($matches[0][$key], $insert, $this->template);
			}
		}		
	}
	
	/**
	 * Builds document contents from template and sapi description
	 * 
	 * @return string
	 */
	function build_page(){

		$this->check_inludes();
		$this->check_constants();

		while (!$this->qc_passed or !$this->pi_passed or !$this->sdc_passed or !$this->ddc_passed or !$this->val_passed) {
			$this->check_qc();
			$this->check_pi();
			if ($this->qc_passed and $this->pi_passed) {
				$this->check_sdc();
			}
			if ($this->qc_passed and $this->pi_passed and $this->sdc_passed) {
				$this->check_ddc();
				//			$this->check_qc();
			}
			if ($this->qc_passed and $this->pi_passed and $this->sdc_passed and $this->ddc_passed) {
				$this->check_val();
			}
		}

		
		
		$this->check_constants();


		//Display TRACE info if requested
		if(TRACE and $this->name=="sapi_env"){
			$senv="";
			$spage="";

			foreach ($this->env as $key=>$value) {
				$senv.=preg_replace("/&lt;\?(.*)\?&gt;/isU", "\\1", highlight_string('<?$env["' . $key . '"] = '.(var_export($value, 1)).'; ?>', true)) . '<br />';
			}

			foreach ($this->env["page"] as $key=>$value) {
				$spage.=preg_replace("/&lt;\?(.*)\?&gt;/isU", "\\1", highlight_string('<?$env["page"]["' . $key . '"] = '.(var_export($value, 1)).'; ?>', true)) . '<br />';
			}
			$sobj="<b>Static Data Containers</b><br /><br />";
			if (is_array($this->sapi["sdc"]))
			foreach ($this->sapi["sdc"] as $key=>$value) {
				$sobj.=preg_replace("/&lt;\?(.*)\?&gt;/isU", "\\1", highlight_string('<?[' . $key . '] = '.(var_export($value, 1)).'; ?>', true)) . '<br />';
			}
			$sobj.="<br /><b>Dynamic Data Containers</b><br /><br />";
			if (is_array($this->sapi["ddc"]))
			foreach ($this->sapi["ddc"] as $key=>$value) {
				$sobj.=preg_replace("/&lt;\?(.*)\?&gt;/isU", "\\1", highlight_string('<?[' . $key . '] = '.(var_export($value, 1)).'; ?>', true)) . '<br />';
			}

			$this->template .= '
			<style>
			div.dump {
				position: absolute; bottom: 20px;
				height: 200px; width: 100%;
				overflow: auto;
				background-color: #efefef;
				background-image: url('.$this->env["http_path"].'usr/system/images/stamp.png);
				background-position: 99% 10px;
				background-repeat: no-repeat;
				border: 1px dashed Gray;
				font-size: 11px; font-family: Verdana, Arial;
				padding: 10px;
			}
			</style>
			<script type="text/javascript">
			function sa_toggle(id, ipref){
				if(!ipref) ipref="il";
				if(document.getElementById(id).style.display=="none") {
					document.getElementById(id).style.display="block";
					document.getElementById(id+"_status").src="'.$this->env["http_path"].'usr/system/images/"+ipref+"minus.gif";
				}else{
					document.getElementById(id).style.display="none";
					document.getElementById(id+"_status").src="'.$this->env["http_path"].'usr/system/images/"+ipref+"plus.gif";
				}
				return false;
			}
			</script>
		
			<div style="position: absolute; z-index: 9000; width: 100%; background-color: black; color: white; font-size: 12px; font-family: Verdana, Arial; font-weight: bold; padding: 4px;">
			<a href="#bottom" style="color: white; text-decoration: none;" onclick="return sa_toggle(\'sa_envdump\')">Environment&nbsp;<div style="margin-top: 1px; position: absolute;"><img id="sa_envdump_status" src="'.$this->env["http_path"].'usr/system/images/ilplus.gif" /></div></a>
			&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
			<a href="#bottom" style="color: white; text-decoration: none;" onclick="return sa_toggle(\'sa_pagedump\')">Page Data&nbsp;<div style="margin-top: 1px; position: absolute;"><img id="sa_pagedump_status" src="'.$this->env["http_path"].'usr/system/images/ilplus.gif" /></div></a>
			&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
			<a href="#bottom" style="color: white; text-decoration: none;" onclick="return sa_toggle(\'sa_objdump\')">SAPI Objects&nbsp;<div style="margin-top: 1px; position: absolute;"><img id="sa_objdump_status" src="'.$this->env["http_path"].'usr/system/images/ilplus.gif" /></div></a>
			&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
			Template: '.$this->env["document.template"].'
			&nbsp;&nbsp;&nbsp;&nbsp;
			Page generation time: ##gentime##
			</div><div id="sa_envdump" style="display: none;" class="dump"><b>SAPID Environment Variables</b><br /><br />'.$senv.'</div>
			</div><div id="sa_pagedump" style="display: none;" class="dump"><b>Page Data</b><br /><br />'.$spage.'</div>
			</div><div id="sa_objdump" style="display: none;" class="dump"><b>SAPI Objects</b><br /><br />'.$sobj.'</div>';

		}
		return $this->template;
	} //\\build_page

	/**
	 * Processses eval error
	 *
	 * @param $code string
	 * @return string
	 */
	function compile_error($code){
		$this->env["error_cnt"]++;
		if(DEBUG)
		return '<div style="border: 1px solid red; color: white; background-color: red; font-weight: bold; cursor: pointer;" align="center" onclick="if(document.getElementById(\'error_'.$this->env["error_cnt"].'\').style.display!=\'block\') document.getElementById(\'error_'.$this->env["error_cnt"].'\').style.display=\'block\'; else document.getElementById(\'error_'.$this->env["error_cnt"].'\').style.display=\'none\';">PHP error #'.$this->env["error_cnt"].'</div><div id="error_'.$this->env["error_cnt"].'" style="position: absolute; width: 700px; background-color: #dfdfdf; border: 1px solid red; padding: 3px; display: none; margin-top: 2px;"><b>Eval\'ed code:</b><br /><br />'.highlight_string("<?\n".$code."\n?>", true).'</div>';
		else return "";
	} //\\compile_error


} //\\sapi_core



?>